package org.yi.web.post.entity;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.yi.core.annotation.TableBind;
import org.yi.core.common.Constants;
import org.yi.core.enums.PostStateEnum;
import org.yi.core.model.Pagination;
import org.yi.web.block.entity.BlockEntity;
import org.yi.web.category.entity.CategoryEntity;

import com.jfinal.core.Controller;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Model;
import com.jfinal.plugin.activerecord.Page;

@TableBind(name="f_post")
public class PostEntity extends Model<PostEntity> {

	private static final Logger logger = LoggerFactory.getLogger(PostEntity.class);
	
	private static final long serialVersionUID = -2051861834676654179L;

	public static PostEntity dao = new PostEntity();

	/**
	 * 
	 * @param pager
	 * @param p
	 * @return
	 * @throws Exception
	 */
	public Page<PostEntity> getPager(Pagination pager, Map<String, String> p) throws Exception {
		String select = "select * ";
		StringBuffer where = new StringBuffer("from f_post where state != ?");
		List<Object> params = new ArrayList<Object>();
		params.add(PostStateEnum.DELETE.getCode());
		// category == 0 说明不过滤category
		if(StringUtils.isNotBlank(p.get("category")) && (Integer.parseInt(p.get("category")) > 0)) {
			where.append("and category = ?");
			params.add(p.get("category"));
		}
		if(StringUtils.isNotBlank(p.get("state"))){
			where.append("and state = ?");
			params.add(p.get("state"));
		}
		if(StringUtils.isNotBlank(p.get("title"))){
			where.append("and title like ?");
			params.add("%"+p.get("title")+"%");
		}
		if(StringUtils.isNotBlank(p.get("type"))){
			where.append("and type = ?");
			params.add(p.get("type"));
		}
		if(StringUtils.isNotBlank(p.get("createTimeMin"))){
			where.append("and create_time >= ?");
			params.add(p.get("createTimeMin"));
		}
		if(StringUtils.isNotBlank(p.get("createTimeMax"))){
			where.append("and create_time < ?");
			params.add(p.get("createTimeMax"));
		}
		where.append(" order by create_time desc");
		return dao.paginate(pager.getPn(), pager.getSize(), select, where.toString(), params.toArray());
	}
	
	public Page<PostEntity> getRecyclePager(Pagination pager, Controller c) throws Exception {
		String select = "select * ";
		StringBuffer where = new StringBuffer("from f_post where 1=1 and state = ?");
		List<Object> params = new ArrayList<Object>();
		params.add(PostStateEnum.DELETE.getCode());
		if(StringUtils.isNotBlank(c.getPara("category"))) {
			where.append("and category = ?");
			params.add(c.getPara("category"));
		}
		if(StringUtils.isNotBlank(c.getPara("title"))){
			where.append("and title like ?");
			params.add("'%"+c.getPara("title")+"%'");
		}
		if(StringUtils.isNotBlank(c.getPara("createTimeMin"))){
			where.append("and create_time >= ?");
			params.add(c.getPara("createTimeMin"));
		}
		if(StringUtils.isNotBlank(c.getPara("createTimeMax"))){
			where.append("and create_time < ?");
			params.add(c.getPara("createTimeMax"));
		}
		return dao.paginate(pager.getPn(), pager.getSize(), select, where.toString(), params.toArray());
	}

	public Object getByTitle(String title) throws Exception {
		String sql = "select * from f_post where title = ?";
		return dao.findFirst(sql, title);
	}

	public void recycle(String... idArr) throws Exception {
		String sql = "update f_post set state = ? where id = ?";
		Object[][] params = new Object[idArr.length][2];
		for(int i=0;i<idArr.length;i++) {
			params[i][0] = PostStateEnum.DELETE.getCode();
			params[i][1] = idArr[i];
		}
		Db.batch(sql, params, Constants.DEFAULT_BATCH_SIZE);
	}

	public void unRecycle(String[] idArr) throws Exception {
		String sql = "update f_post set state = ? where id = ?";
		Object[][] params = new Object[idArr.length][2];
		for(int i=0;i<idArr.length;i++) {
			params[i][0] = PostStateEnum.PUBLISH.getCode();
			params[i][1] = idArr[i];
		}
		Db.batch(sql, params, Constants.DEFAULT_BATCH_SIZE);
	}

	public void deleteAll() throws Exception {
		String sql = "delete from f_post where state = ? ";
		Db.update(sql, PostStateEnum.DELETE.getCode());
	}
	
	/**
	 * get some article by conditions
	 * @param p
	 * @throws Exception 
	 */
	public List<PostEntity> getSome(Map<String, String> p) throws Exception {
		return getSome(p, null);
	}
	
	public List<PostEntity> getSome(Map<String, String> p, Integer limit) throws Exception{
		StringBuffer sql = new StringBuffer("select * from f_post where 1=1 ");
		List<Object> params = new ArrayList<Object>();
		
		sql.append(" and state = ? ");
		params.add(PostStateEnum.PUBLISH.getCode());
		
		if(p != null) {
			if(StringUtils.isNotBlank(p.get("category"))) {
				sql.append("and category = ?");
				params.add(p.get("category"));
			}
			if(StringUtils.isNotBlank(p.get("state"))){
				sql.append("and state = ?");
				params.add(p.get("state"));
			}
			if(StringUtils.isNotBlank(p.get("flag_suggest"))){
				sql.append("and flag_suggest = ?");
				params.add(p.get("flag_suggest"));
			}
			if(StringUtils.isNotBlank(p.get("flag_image"))){
				sql.append("and flag_image = ?");
				params.add(p.get("flag_image"));
			}
			if(StringUtils.isNotBlank(p.get("flag_top"))){
				sql.append("and flag_top = ?");
				params.add(p.get("flag_top"));
			}
			if(StringUtils.isNotBlank(p.get("flag_carousel"))){
				sql.append("and flag_carousel = ?");
				params.add(p.get("flag_carousel"));
			}
			if(StringUtils.isNotBlank(p.get("title"))){
				sql.append("and title like ?");
				params.add("%"+p.get("title")+"%");
			}
		}
		sql.append(" order by create_time desc ");
		if(limit != null) {
			sql.append(" limit 0, " + limit);
		}
		return dao.find(sql.toString(), params.toArray());
	}
	
	public List<PostEntity> getSuggest() throws Exception {
		return getSuggest(15);
	}
	
	public List<PostEntity> getSuggest(Integer limit) throws Exception {
		Map<String,String> p = new HashMap<String,String>();
		p.put("flag_suggest", "1");
		return getSome(p, limit);
	}
	
	public List<PostEntity> getRecent() throws Exception {
		return getRecent(15);
	}

	public List<PostEntity> getRecent(Integer limit) throws Exception {
		return getSome(null, limit);
	}
	
	public List<PostEntity> getByBlock(BlockEntity b) throws Exception {
		if(b == null) {
			return null;
		}
		StringBuffer sql = new StringBuffer("select * from f_post where state = '"  + PostStateEnum.PUBLISH.getCode() + "'");
		List<Object> param = new ArrayList<Object>();
		if(b.get("category") != null && StringUtils.isNotBlank(String.valueOf(b.get("category")))) {
			sql.append(" and category = ?");
			param.add(b.get("category"));
		}
		if(b.get("post_type") != null && StringUtils.isNotBlank(String.valueOf(b.get("post_type")))) {
			sql.append(" and type = ?");
			param.add(b.get("post_type"));
		}
		if(b.get("sort_field") != null && StringUtils.isNotBlank(String.valueOf(b.get("sort_field")))) {
			sql.append(" order by " + b.get("sort_field"));
			if(Constants.BLOCK_ORDER_ASC.equals(String.valueOf(b.get("asc")))) {
				sql.append(" asc");
			} else {
				sql.append(" desc");
			}
		}
		if(b.get("limit") != null) {
			sql.append(" limit ");
			if(b.get("start") != null) { 
				sql.append(b.get("start") + ",");
			}
			sql.append(b.get("limit"));
		}
		logger.debug("sql: {}, param: {}", sql, ArrayUtils.toString(param.toArray()));
		return dao.find(sql.toString(), param.toArray());
	}

	public List<PostEntity> getByIdListForBlock(BlockEntity b) throws Exception {
		if(b == null || b.get("content") == null || StringUtils.isBlank(b.getStr("content"))) {
			return null;
		}
		String ids = b.getStr("content");
		ids = StringUtils.replace(ids, "，", ",");
		String[] idArr = StringUtils.split(ids, ",");
		return getByIdList((Object[])idArr);
	}

	public List<PostEntity> getRandom(BlockEntity b) throws Exception {
		return getRandom(b, null);
	}

	public List<PostEntity> getRandom(BlockEntity b, String cid) {
		String where1 = "", where2 = "";
		if(StringUtils.isNotBlank(cid)) {
			where1 = " where state = "+PostStateEnum.PUBLISH.getCode()+" and category = " + cid;
			where2 = " and state = "+PostStateEnum.PUBLISH.getCode()+" and category = " + cid;
		}
		String sql = "(SELECT * FROM f_post AS t1 " + 
				" JOIN (SELECT ROUND(RAND() * ((SELECT MAX(id) FROM f_post" 
						+ where1 + ")-(SELECT MIN(id) FROM f_post" 
						+ where1 + ")) +(SELECT MIN(id) FROM f_post "
						+ where1 + "))AS id) AS t2" + 
				" WHERE t1.id >= t2.id " + where2 +
				" ORDER BY t1.id LIMIT 1)";
		int limit = (Integer) (b.get("limit") == null ? Constants.DEFAULT_PAGESIZE : b.get("limit"));
		StringBuffer s = new StringBuffer(sql);
		for(int i=1;i<limit;i++) {
			s.append(" union ").append(sql);
		}
		return dao.find(s.toString());
	}

	public PostEntity getLast(PostEntity p) {
		String sql = "select * from f_post where id < ? and state = "+PostStateEnum.PUBLISH.getCode()+" order by id desc limit 1";
		return dao.findFirst(sql, p.get("id"));
	}
	public PostEntity getNext(PostEntity p) {
		String sql = "select * from f_post where id > ? and state = "+PostStateEnum.PUBLISH.getCode()+" order by id asc limit 1";
		return dao.findFirst(sql, p.get("id"));
	}
	
	public List<PostEntity> getNext(PostEntity p, Integer limit) {
		String sql = "select * from f_post where id > ? and state = "+PostStateEnum.PUBLISH.getCode()+" order by id asc limit 0, ?";
		return dao.find(sql, (p==null || p.get("id")==null) ? 0 : p.get("id"), limit);
	}

	public List<PostEntity> getByCategory(CategoryEntity c) throws Exception {
		Map<String,String> params = new HashMap<String,String>();
		params.put("category", String.valueOf(c.get("id")));
		return getSome(params);
	}

	public void like(String articleId) {
		String sql = "update f_post set like_num = like_num + 1 where id = ?";
		Db.update(sql, articleId);
	}

	public void updateFavorite(String articleId, boolean isAdd) {
		String sql = "update f_post set favorite_num = favorite_num " + (isAdd?"+":"-")  +" 1 where id = ?";
		Db.update(sql, articleId);
	}

	public void updateReadNum(PostEntity p) {
		String sql = "update f_post set read_num = read_num + 1 where id = ?";
		Db.update(sql, p.get("id"));
	}

	public List<PostEntity> getByIdList(Object... idList) {
		StringBuffer sql = new StringBuffer();
		List<Object> params = new ArrayList<Object>();
		for(Object o : idList) {
			sql.append("select * from f_post where id = ? union ");
			params.add(o);
		}
		sql.append("SELECT * FROM f_post WHERE 1=2");
		logger.debug("sql: {}, param: {}", sql, ArrayUtils.toString(params.toArray()));
		return dao.find(sql.toString(), params.toArray());
	}

}
